package com.gw.core.protocol;

import com.gw.core.config.Config;
import com.gw.core.message.Message;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * Description: 消息的编解码器
 *
 * @author LinHuiBa-YanAn
 * @date 2023/8/7 20:49
 */
@Slf4j
@ChannelHandler.Sharable
public class MessageCodecSharable extends MessageToMessageCodec<ByteBuf, Message> {
    @Override
    public void encode(ChannelHandlerContext ctx, Message msg, List<Object> outList) throws Exception {
        ByteBuf out = ctx.alloc().buffer();
        // 1. 4个字节的魔数
        out.writeBytes(new byte[]{1, 2, 3, 4});
        // 2. 1 字节的版本
        out.writeByte(1);
        // 3. 1 字节的序列化方式 jdk 0 , json 1
        out.writeByte(Config.getSerializerAlgorithm().ordinal());
        // 4. 1 字节的消息指令类型
        out.writeByte(msg.getMessageType());
        // 5. 4 个字节请求序号
        out.writeInt(msg.getSequenceId());
        // 填充位（以上共11个字节，固加上一个字节做填充位）
        out.writeByte(0xff);
        // 获取内容的字节数组
        byte[] bytes = Config.getSerializerAlgorithm().serialize(msg);
        // 长度
        out.writeInt(bytes.length);
        // 消息正文
        out.writeBytes(bytes);
        outList.add(out);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        // 读取魔术
        int magicNum = in.readInt();
        // 读取版本
        byte version = in.readByte();
        // 读取序列化方法
        byte serializerAlgorithm = in.readByte();
        // 读取消息指令类型
        byte messageType = in.readByte();
        // 读取请求序号
        int sequenceId = in.readInt();
        // 读取无意义的对齐填充
        in.readByte();
        // 读取长度
        int length = in.readInt();
        // 读取正文
        byte[] bytes = new byte[length];
        in.readBytes(bytes, 0, length);

        // 获取序列化算法
        Serializer.Algorithm algorithm = Serializer.Algorithm.values()[serializerAlgorithm];
        // 根据消息指令类型获取消息类型
        Class<? extends Message> messageClass = Message.getMessageClass(messageType);
        // 将字节数组反序列化成消息指令对象
        Message message = algorithm.deserialize(messageClass, bytes);
        out.add(message);
    }

}

